﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Media;
using FMOD;

namespace LaunchPad.Core.Controls.Tracks
{
    public class VirtualSampleProvider
    {
        private static readonly TimeSpan SnippetLength = TimeSpan.FromSeconds(1);
        private static readonly SolidColorBrush[] ChannelBrushes = {Brushes.Red, Brushes.Blue};

        public VirtualSampleProvider(AudioTrack track)
        {
            AudioTrack = track;
        }

        public AudioTrack AudioTrack { get; private set; }

        public IEnumerable<VirtualSnippet> GetSnippets(double widthPerSecond, WorkProgressCallback progressCallback)
        {
            /* First we gather all snippets so we can process them in parallel */
            TimeSpan length = AudioTrack.Length;
            int snippetCount = Convert.ToInt32(length.TotalMilliseconds/SnippetLength.TotalMilliseconds);
            var snippets = new List<Snippet>();

            /* Calculate the amount of work we're going to have to do here */
            if(progressCallback != null)
                progressCallback.TotalWork = snippetCount*10;

            TimeSpan timeOffset = TimeSpan.Zero;
            for (int i = 0; i < snippetCount; i++)
            {
                /* Allows for defered parallel processing of samples */
                var snippet = AudioTrack.GetUnprocessedSnippet(timeOffset, SnippetLength);
                snippets.Add(snippet);
                timeOffset += SnippetLength;
                if (progressCallback != null)
                    progressCallback.WorkComplete(6);
            }

            /* Process all samples */
            snippets.AsParallel().ForAll(s =>
                                             {
                                                 s.Process(1000);
                                                 if (progressCallback != null)
                                                     progressCallback.WorkComplete(3);
                                             });

            /* Generate graphical snippets */
            double snippetWidth = widthPerSecond*SnippetLength.TotalMilliseconds/1000;
            var channelPrevious =
                new List<VirtualSnippet>(Enumerable.Repeat<VirtualSnippet>(null, AudioTrack.ChannelCount));

            foreach (var trackSnippet in snippets)
            {
                for (int channelNo = 0; channelNo < trackSnippet.Channels.Count; channelNo++)
                {
                    double offset = 0;
                    var previous = channelPrevious[channelNo];
                    if (previous != null)
                        offset = previous.Bounds.Right;

                    var data = trackSnippet.Channels[channelNo].Data;
                    //var spectralData = trackSnippet.Channels[channelNo].SpectralData;

                    if (data == null)
                        continue;

                    var snippet = new VirtualSnippet(offset, snippetWidth, data, ChannelBrushes[channelNo]);

                    channelPrevious[channelNo] = snippet;
                    channelNo++;

                    yield return snippet;
                }

                if (progressCallback != null)
                    progressCallback.WorkUnitComplete();
            }
        }
    }
}